﻿using CrawlerApp.Core.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;

namespace CrawlerApp.Core.Entities.BookAggregate
{
    public class Book : BaseEntity, IAggregateRoot
    {
        public string Name { get; private set; }
        public string Href { get; private set; }
        public Category Category { get; private set; }
        private readonly List<Tag> _tags = new List<Tag>();
        public IEnumerable<Tag> Tags
        {
            get { return _tags; }
        }
        public Author Author { get; private set; }
        public string Intro { get; private set; }
        public string Cover { get; private set; }
        public BookVote Vote { get; private set; } = new BookVote(0, 0, 0, 0, 0);
        public BookResource Resource { get; private set; } = new BookResource();

        public Book(string name, string href)
        {
            Name = name;
            Href = href;
        }
        public Book AddCategory(Category category)
        {
            Category = category;
            return this;
        }
        public Book AddAuthor(Author author)
        {
            Author = author;
            return this;
        }
        public Book AddIntro(string intro)
        {
            Intro = intro;
            return this;
        }
        public Book AddCover(string cover)
        {
            Cover = cover;
            return this;
        }
        public Book AddResource(BookResource resource)
        {
            Resource = resource;
            return this;
        }
        public Book AddTag(Tag tag)
        {
            if (tag == null) throw new ArgumentNullException(nameof(tag));

            if (!_tags.Exists(t => t.Name == tag.Name || t.Href == tag.Href))
            {
                _tags.Add(tag);
            }

            return this;
        }
        public Book RemoveTag(Tag tag)
        {
            if (tag == null) throw new ArgumentNullException(nameof(tag));

            var t = _tags.SingleOrDefault(it => it.Name == tag.Name || it.Href == tag.Href);
            if (t != null)
            {
                _tags.Remove(t);
            }

            return this;
        }
        public Book AddRangeTag(List<Tag> tags)
        {
            if (tags == null) throw new ArgumentNullException(nameof(tags));

            tags.ForEach(tag => AddTag(tag));

            return this;
        }
        public Book RemoveRangeTag(List<Tag> tags)
        {
            if (tags == null) throw new ArgumentNullException(nameof(tags));

            tags.ForEach(tag => RemoveTag(tag));

            return this;
        }
        public Book ClearTag()
        {
            _tags.Clear();
            return this;
        }
        public Book VoteModify(int great, int good, int normal, int worse, int bad)
        {
            Vote.Update(great, good, normal, worse, bad);

            return this;
        }
    }
}
